package com.hlkj.warboot.configurer.redis;

import com.hlkj.warboot.configurer.util.LoggerUtil;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description redis持久化Bean
 * @Author 李星
 * @Date 2019/6/29 22:50
 */
//@Component
public class RedisDao {

    @Resource
    private RedisTemplate<String, Object> redisTemplate; // redis持久化模板Bean对象（多线程并发下线程安全）

    // TODO 检查key是否存在
    public Boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    // TODO 删除key
    public void del(String key) {
        redisTemplate.delete(key);
    }

    public void del(String... keys) {
        Set<String> kSet = Stream.of(keys).collect(Collectors.toSet());
        redisTemplate.delete(kSet);
    }

    public void del(Collection<String> keys) {
        Set<String> kSet = new HashSet<>(keys);
        redisTemplate.delete(kSet);
    }

    // TODO 设置key多少秒后过期，单位：秒
    public void expire(String key, long time) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    // TODO 设置key在某个日期上过期
    public void expire(String key, Date date) {
        redisTemplate.expireAt(key, date);
    }

    // TODO 查询key的生命周期倒计时，单位：秒
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    // TODO 将key设置为永久有效
    public void persist(String key) {
        redisTemplate.persist(key);
    }

    // ========================================================字符串=========================================================
    // TODO 添加字符串
    public void stringSet(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加字符串】出现错误：" + e.getMessage());
        }
    }

    public boolean stringSet(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                stringSet(key, value);
            }
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加字符串，附加过期时间】出现错误：" + e.getMessage());
            return false;
        }
    }

    // TODO 查询字符串
    public Object stringGet(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    // TODO 递增、递减
    public Long increment(String key, int num) {
        try {
            return redisTemplate.opsForValue().increment(key, num);
        } catch (Exception e) {
            return 0L;
        }
    }

    // ============================================================哈希=============================================================
    // TODO 添加哈希列表
    public Boolean hashSet(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加哈希】出现错误：" + e.getMessage());
            return false;
        }
    }

    public boolean hashSet(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加哈希，附加过期时间】出现错误：" + e.getMessage());
            return false;
        }
    }

    // TODO 查询哈希中的某个属性
    public Object hashGetField(String key, String field) {
        return redisTemplate.opsForHash().get(key, field);
    }

    // TODO 查询哈希列表中所有属性
    public Map<Object, Object> hashGetAllField(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    // TODO 判断哈希列表中是否含有某个属性
    public boolean hashHasField(String key, String field) {
        return redisTemplate.opsForHash().hasKey(key, field);
    }

    // TODO 编辑哈希列表中的某个属性，不存在就创建
    public boolean hashModifyField(String key, String field, Object value) {
        try {
            redisTemplate.opsForHash().put(key, field, value);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 编辑哈希中的某个属性，不存在就创建】出现错误：" + e.getMessage());
            return false;
        }
    }

    public boolean hashModifyField(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 编辑哈希中的某个属性，不存在就创建，附加过期时间】出现错误：" + e.getMessage());
            return false;
        }
    }

    //  TODO 删除哈希列表中的属性（一个或多个）
    public void hashDelField(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    // ==============================================================List(列表)================================================================
    // TODO 获取列表的大小
    public Long listLen(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 查询列表的大小】出现错误：" + e.getMessage());
            return null;
        }
    }

    // TODO 根据索引查询列表中的元素
    public Object listIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 根据索引查询列表中的元素】出现错误：" + e.getMessage());
            return null;
        }
    }

    public List<Object> listRange(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 根据索引区间查询列表中的元素】出现错误：" + e.getMessage());
            return null;
        }
    }

    // TODO 添加元素到列表
    public boolean listPush(String key, Object value) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加元素到列表】出现错误：" + e.getMessage());
            return false;
        }
    }

    public boolean listPush(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加元素到列表，附加过期时间】出现错误：" + e.getMessage());
            return false;
        }
    }

    public boolean listPush(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加集合到列表】出现错误：" + e.getMessage());
            return false;
        }
    }

    public boolean listPush(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().leftPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加集合到列表，附加过期时间】出现错误：" + e.getMessage());
            return false;
        }
    }

    // TODO 删除列表中的元素（一个或者多个）
    public Long listRem(String key, long count, Object value) {
        try {
            return redisTemplate.opsForList().remove(key, count, value);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 更具值删除列表中的元素】出现错误：" + e.getMessage());
            return null;
        }
    }

    /*
     * @Description TODO 根据索引更新列表中的元素
     * @Author 李星
     * @Date 2019/6/18 22:26
     * @Param [key, index, value]
     * @return boolean
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 根据索引更新列表中的元素】出现错误：" + e.getMessage());
            return false;
        }
    }

    // ========================================================Set(集合)=========================================================
    // TODO 获取集合的大小
    public Long setLen(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 获取集合的大小】出现错误：" + e.getMessage());
            return null;
        }
    }

    // TODO 查询集合中的所有元素
    public Set<Object> setSmembers(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 查询集合中的所有元素】出现错误：" + e.getMessage());
            return null;
        }
    }

    // TODO 判断当前值是否在集合中
    public Boolean setSisMember(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 判断当前值是否在集合中】出现错误：" + e.getMessage());
            return false;
        }
    }

    // TODO 添加元素（一个或多个）到集合
    public Long setAdd(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加元素（一个或多个）到集合】出现错误：" + e.getMessage());
            return null;
        }
    }

    public Long setAdd(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 添加元素（一个或多个）到集合，附加过期时间】出现错误：" + e.getMessage());
            return null;
        }
    }

    // TODO 删除集合中的元素（一个或多个）
    public Long setRem(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().remove(key, values);
        } catch (Exception e) {
            LoggerUtil.error("【REDIS 删除集合中的元素（一个或多个）】出现错误：" + e.getMessage());
            return null;
        }
    }

}
